(define (caar x) (car (car x)))

(define (cadr x) (car (cdr x)))

(define (cdar x) (cdr (car x)))

(define (cddr x) (cdr (cdr x)))

; Some utility functions that you may find useful to implement
(define (zip pairs)
  (cond
    ((eqv? (car pairs) nil)
     nil)
    (else
     (cons (map car pairs) (zip (map cdr pairs))))))

; ; Problem 5
; ; Returns a list of two-element lists
(define (enumerate s)
  ; BEGIN PROBLEM 5
  (define (enum_in b s)
    (cond
      ((eqv? s nil)
       nil)
      (#t
       (cons (cons b (cons (car s) nil))
             (enum_in (+ b 1) (cdr s))))))
  (enum_in 0 s))

; END PROBLEM 5
; ; Problem 6
; ; Merge two lists LIST1 and LIST2 according to COMP and return
; ; the merged lists.
(define (merge comp list1 list2)
  ; BEGIN PROBLEM 6
  (cond
    ((and (eqv? list1 nil) (eqv? list2 nil))
     nil)
    ((or (eqv? list1 nil)
         (and (not (eqv? list2 nil))
              (comp (car list2) (car list1))))
     (cons (car list2) (merge comp list1 (cdr list2))))
    (#t
     (cons (car list1) (merge comp (cdr list1) list2)))))

; END PROBLEM 6
; ; Returns a function that checks if an expression is the special form FORM
(define (check-special form)
  (lambda (expr) (equal? form (car expr))))

; ; Problem 7
(define lambda? (check-special 'lambda))

(define define? (check-special 'define))

(define quoted? (check-special 'quote))

(define let? (check-special 'let))

; ; Converts all let special forms in EXPR into equivalent forms using lambda
(define (let-to-lambda expr)
  (cond 
    ((atom? expr)
     ; BEGIN PROBLEM 7
     expr
     ; END PROBLEM 7
    )
    ((quoted? expr)
     ; BEGIN PROBLEM 7
     expr
     ; END PROBLEM 7
    )
    ((or (lambda? expr) (define? expr))
     (let ((form (car expr))
           (params (cadr expr))
           (body (cddr expr)))
       ; BEGIN PROBLEM 7
       (cons form (cons params (map let-to-lambda body)))
       ; END PROBLEM 7
     ))
    ((let? expr)
     (let ((values (cadr expr))
           (body (cddr expr)))
       ; BEGIN PROBLEM 7
       (define values (zip values))
       (define forms (car values))
       (define inits (cadr values))
       (cons (cons 'lambda
                   (cons forms (map let-to-lambda body)))
             (map let-to-lambda inits))
       ; END PROBLEM 7
     ))
    (else
     ; BEGIN PROBLEM 7
     (map let-to-lambda expr)
     ; END PROBLEM 7
    )))
